import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
import { HYConfig, HYRequestInterceptors } from '@/service/request/type'
import { ElMessage } from 'element-plus'
import router from '@/router'

class HYRequest {
  instance: AxiosInstance
  interceptors?: HYRequestInterceptors
  constructor(config: HYConfig) {
    this.instance = axios.create(config)
    this.interceptors = config.interceptors

    // 单个实例的拦截器
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptors,
      this.interceptors?.requestInterceptorsCatch
    )

    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptors,
      this.interceptors?.responseInterceptorsCatch
    )

    // 全部实例的拦截器
    this.instance.interceptors.response.use(
      (res) => {
        return res.data
      },
      (err) => {
        const data = err.response.data
        if (data.code === 401) {
          ElMessage.error(data.message + ', 请重新登陆!')
          setTimeout(() => {
            window.localStorage.clear()
            router.push('/login')
          }, 3000)
        }
        const status = err.response.status
        if (status === 500) {
          ElMessage.error(err.message)
        }
        return Promise.reject('错误')
      }
    )
    this.instance.interceptors.request.use((res) => {
      res.headers['token'] = localStorage.getItem('token') ?? ''
      return res
    })
  }

  request<T>(config: HYConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      this.instance
        .request<any, any>(config)
        .then((res) => {
          if (config.interceptors?.responseInterceptors) {
            res = config.interceptors.responseInterceptors(res)
          }
          resolve(res)
        })
        .catch((err) => reject(err))
    })
  }

  get<T>(config: AxiosRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'get' })
  }

  post<T>(config: AxiosRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'post' })
  }

  put<T>(config: AxiosRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'put' })
  }

  delete<T>(config: AxiosRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'delete' })
  }

  // 下载
  postDown(config: AxiosRequestConfig, name: string): void {
    this.request({ ...config, method: 'post', responseType: 'blob' }).then(
      (res) => {
        const a = document.createElement('a')
        a.href = URL.createObjectURL(res)
        a.download = name
        a.style.display = 'none'
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
      }
    )
  }

  getDown(config: AxiosRequestConfig, name: string): void {
    this.request({ ...config, method: 'get', responseType: 'blob' }).then(
      (res) => {
        const a = document.createElement('a')
        a.href = URL.createObjectURL(res)
        a.download = name
        a.style.display = 'none'
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
      }
    )
  }
}

export default HYRequest
